#include "stdio.h"
#include "shdef.h"


#ifndef FINSH_ARG_MAX
#define FINSH_ARG_MAX    8
#endif

extern void *rt_memmove(void *dest, const void *src, rt_ubase_t n);
extern void *rt_memset(void *s, int c, rt_ubase_t count);
extern void *rt_memcpy(void *dst, const void *src, rt_ubase_t count);
extern rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_ubase_t count);
extern char *rt_strncpy(char *dst, const char *src, rt_ubase_t n);
extern rt_int32_t rt_strncmp(const char *cs, const char *ct, rt_ubase_t count);
extern rt_int32_t rt_strcmp(const char *cs, const char *ct);

//extern cmd_desc_t cmd_syscall_table[];


int help(int argc, char* argv[]);
extern int debug_string(int argc,char* argv[]);
extern int getvgl_time(int argc,char* argv[]);

extern int spiflash_fs_test(int argc,char* argv[]);
extern int fs_read_file(int argc,char* argv[]);
extern int test_fatfs_demo(int argc,char* argv[]);



cmd_desc_t cmd_syscall_table[]={  //net_ping
	{"help", NULL, help},
	{"debug", NULL, debug_string},
	{"getvgl", NULL, getvgl_time},
	{"flash.fs.test", "flash.fs.test", spiflash_fs_test},
	{"flash.read", "flash.read address lenght ", fs_read_file},
	{"fatfs.test", "fatfs.test ", test_fatfs_demo},
	{NULL,NULL,NULL}, //server_ctl_cmd_interface  debug_string
};  //

int help(int argc, char* argv[])
{
	int i;
	printf("\r\n Uage :  \r\n");
	for (i = 0; i < sizeof(cmd_syscall_table)/sizeof(cmd_syscall_table[0])-1;i++){
		printf (" --> %s \r\n",cmd_syscall_table[i].name);
		   if (cmd_syscall_table[i].desc !=NULL)
		   	 printf ("     --> %s \r\n",cmd_syscall_table[i].desc);
	}
	
    return 0;
}




static int msh_split(char *cmd, rt_size_t length, char *argv[FINSH_ARG_MAX])
{
    char *ptr;
    rt_size_t position;
    rt_size_t argc;
    rt_size_t i;

    ptr = cmd;
    position = 0; argc = 0;

    while (position < length)
    {
        /* strip bank and tab */
        while ((*ptr == ' ' || *ptr == '\t') && position < length)
        {
            *ptr = '\0';
            ptr ++; position ++;
        }

        if(argc >= FINSH_ARG_MAX)
        {
            rt_kprintf("Too many args ! We only Use:\n");
            for(i = 0; i < argc; i++)
            {
                rt_kprintf("%s ", argv[i]);
            }
            rt_kprintf("\n");
            break;
        }

        if (position >= length) break;

        /* handle string */
        if (*ptr == '"')
        {
            ptr ++; position ++;
            argv[argc] = ptr; argc ++;

            /* skip this string */
            while (*ptr != '"' && position < length)
            {
                if (*ptr == '\\')
                {
                    if (*(ptr + 1) == '"')
                    {
                        ptr ++; position ++;
                    }
                }
                ptr ++; position ++;
            }
            if (position >= length) break;

            /* skip '"' */
            *ptr = '\0'; ptr ++; position ++;
        }
        else
        {
            argv[argc] = ptr;
            argc ++;
            while ((*ptr != ' ' && *ptr != '\t') && position < length)
            {
                ptr ++; position ++;
            }
            if (position >= length) break;
        }
    }

    return argc;
}

//static int cmd_line_split(char* cmd, int length, char* argv[FINSH_ARG_MAX])
//{
//    char *ptr;
//    unsigned long position;
//    unsigned long argc;

//    ptr = cmd;
//    position = 0; argc = 0;

//    while (position < length)
//    {
//        while ((*ptr == ' ' || *ptr == '\t') && position < length)
//        {
//            *ptr = '\0';
//            ptr ++; position ++;
//        }
//        if (position >= length) break;

//        if (*ptr == '"')
//        {
//            ptr ++; position ++;
//            argv[argc] = ptr; argc ++;

//            while (*ptr != '"' && position < length)
//            {
//                if (*ptr == '\\')
//                {
//                    if (*(ptr + 1) == '"')
//                    {
//                        ptr ++; position ++;
//                    }
//                }
//                ptr ++; position ++;
//            }
//            if (position >= length) break;

//            *ptr = '\0'; ptr ++; position ++;
//        }
//        else
//        {
//            argv[argc] = ptr;
//            argc ++;
//            while ((*ptr != ' ' && *ptr != '\t') && position < length)
//            {
//                ptr ++; position ++;
//            }
//            if (position >= length) break;
//        }
//    }

//    return argc;
//}






static cmd_function_t soft_sh_get_cmd(char *cmd, int size)
{
    cmd_desc_t *index;
    int pos = 0;
    cmd_function_t cmd_func = NULL;
    int cmd_size = sizeof(cmd_syscall_table)/sizeof(cmd_syscall_table[0]) - 1;
	
	for ( pos = 0;pos < cmd_size; pos++){
        index = &cmd_syscall_table[pos];
        if (rt_strncmp(index->name, cmd, size) == 0 && index->name[size] == '\0'){
            cmd_func = (cmd_function_t)index->func;
            break;
        }
    }
	
    return cmd_func;
}

//static int _soft_sh_exec_cmd(char* cmd, int length, int *retp,void *result)
//{
//    int argc;
//    int cmd0_size = 0;
//    cmd_function_t cmd_func;
//    char *argv[FINSH_ARG_MAX];
//	
//	if (cmd == NULL)
//		return RT_ERROR;
////   printf(" %s %d \n",__FUNCTION__,__LINE__);
//    while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && cmd0_size < length)
//        cmd0_size ++;
//	
//    if (cmd0_size == 0)
//        return RT_ERROR;
////	printf(" %s %d \n",__FUNCTION__,__LINE__);

//    cmd_func = soft_sh_get_cmd(cmd, cmd0_size);
//    if (cmd_func == NULL){
//		//system(cmd);
//        return  RT_ERROR;
//    }
//    rt_memset(argv, 0x00, sizeof(argv));
//    argc = cmd_line_split(cmd, length, argv);
//    if (argc == 0)
//        return RT_ERROR;

//    //*retp = cmd_func(argc, argv,result);
//		*retp = cmd_func(argc, argv);
//    return 0;
//}


// zhihua

static int _msh_exec_cmd(char *cmd, rt_size_t length, int *retp)
{
    int argc;
    rt_size_t cmd0_size = 0;
    cmd_function_t cmd_func;
    char *argv[FINSH_ARG_MAX];

    RT_ASSERT(cmd);
    RT_ASSERT(retp);

    /* find the size of first command */
    while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && cmd0_size < length)
        cmd0_size ++;
    if (cmd0_size == 0)
        return -RT_ERROR;

    //cmd_func = msh_get_cmd(cmd, cmd0_size);
    cmd_func = soft_sh_get_cmd(cmd, cmd0_size);
    if (cmd_func == RT_NULL)
        return -RT_ERROR;

    /* split arguments */
    rt_memset(argv, 0x00, sizeof(argv));
    argc = msh_split(cmd, length, argv);
    if (argc == 0)
        return -RT_ERROR;

    /* exec this command */
    *retp = cmd_func(argc, argv);
    return 0;
}



int msh_exec(char *cmd, unsigned int length)
{
    int cmd_ret;

    /* strim the beginning of command */
    while (*cmd  == ' ' || *cmd == '\t')
    {
        cmd++;
        length--;
    }

    if (length == 0)
        return 0;

    /* Exec sequence:
     * 1. built-in command
     * 2. module(if enabled)
     */
    if (_msh_exec_cmd(cmd, length, &cmd_ret) == 0)
    {
        return cmd_ret;
    }

    /* truncate the cmd at the first space. */
    {
        char *tcmd;
        tcmd = cmd;
        while (*tcmd != ' ' && *tcmd != '\0')
        {
            tcmd++;
        }
        *tcmd = '\0';
    }
    rt_kprintf("%s: command not found.\r\n", cmd);
    return -1;
}

//static int soft_shell_exec(char* cmd,  int length,void *result)
//{
//    int cmd_ret;

//    while(*cmd  == ' ' || *cmd == '\t'){
//        cmd++;
//        length--;
//    }

//    if (length == 0)
//        return 0;

//	if (_soft_sh_exec_cmd(cmd, length, &cmd_ret,result) == 0){
//        return cmd_ret;
//    }

//    return -1;
//}


